﻿using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Inscriptionem.Controllers.Base;
using Inscriptionem.Extensions;
using Inscriptionem.Localization;
using Inscriptionem.Models.Menu.Requests;
using Inscriptionem.Models.Menu.Views;

namespace Inscriptionem.Controllers
{
    public class MenuController : BaseController
    {
        public ActionResult Sections(SectionsRequestModel model)
        {
            var result = new SectionsViewModel();
            model.CopyTo(result);

            var db = new ORM.DB();

            var language = db.Languages.FirstOrDefault(l => l.Name.ToLower() == model.Language);
            if (language == null)
            {
                language = db.Languages.First(l => l.IsDefault);
            }

            result.Sections.AddRange(language.Sections.OrderBy(s => s.Order));

            return PartialView("Sections", result);
        }

        public ActionResult Languages(LanguagesRequestModel model)
        {
            var result = new LanguagesViewModel();
            model.CopyTo(result);

            var db = new ORM.DB();
            result.Languages.AddRange(db.Languages.OrderBy(l => l.Order));

            return PartialView("Languages", result);
        }

        public ActionResult Pagination(PaginationRequestModel model)
        {
            var result = new PaginationViewModel();
            model.CopyTo(result);

            if (result.MaximumLinkCount <= 0)
            {
                result.MaximumLinkCount = PaginationRequestModel.DefaultMaximumLinkCount;
            }

            result.Links.AddRange(result.TotalPages <= result.MaximumLinkCount ? SimplePagination(model) : ComplexPagination(model));

            return PartialView(string.Format("~/Views/Menu/Pagination{0}.cshtml", (string.IsNullOrWhiteSpace(result.Language) || result.Language == Language.DefaultValue ? string.Empty : "." + result.Language)), result);
        }

        #region Pagination Implementation
        private List<PaginationViewModel.Page> SimplePagination(PaginationRequestModel Model)
        {
            var result = new List<PaginationViewModel.Page>();
            for (int i = 0; i < Model.TotalPages; i++)
            {
                result.Add(new PaginationViewModel.Page()
                {
                    Number = i + 1,
                    IsCurrent = (i + 1) == Model.CurrentPage,
                    URL = Model.UrlTemplate.Replace("{Language}", Model.Language).Replace("{Section}", Model.Section).Replace("{ID}", i.ToString())
                });
            }

            return result;
        }

        private List<PaginationViewModel.Page> ComplexPagination(PaginationRequestModel Model)
        {
            var result = new List<PaginationViewModel.Page>();

            var coreIndicies = Enumerable.Range((Model.CurrentPage - 1 >= 1 ? Model.CurrentPage - 2 : Model.CurrentPage - 1),
                                                (Model.CurrentPage - 1 >= 1 ? ((Model.CurrentPage + 1 <= Model.TotalPages) ? 3 : 2) : ((Model.CurrentPage + 1 <= Model.TotalPages) ? 2 : 1))).ToList();

            var indicies = coreIndicies
                // At the beginning
                .Union(Enumerable.Range(0, Model.MaximumLinkCount/2))
                // At the end
                .Union(Enumerable.Range(Model.TotalPages - Enumerable.Range(0, Model.MaximumLinkCount/2).Count() - 1, Model.MaximumLinkCount - Enumerable.Range(0, Model.MaximumLinkCount/2).Count()))
                .Distinct().OrderBy(i => i).ToList();

            // Remove overhead
            bool isRemoveAtBegin = true;
            while (Model.MaximumLinkCount < indicies.Count)
            {
                int value = 0;
                isRemoveAtBegin = !isRemoveAtBegin;

                if (isRemoveAtBegin)
                {
                    var collection = indicies.Where(i => i < coreIndicies.Min());
                    if(collection.Any())
                    {
                        value =collection.Max();
                    }
                }
                else
                {
                    var collection = indicies.Where(i => i > coreIndicies.Max());
                    if (collection.Any())
                    {
                        value = collection.Min();
                    }
                }

                indicies.Remove(value);
            }

            foreach (int item in indicies)
            {
                result.Add(new PaginationViewModel.Page()
                               {
                                   Number = item + 1,
                                   IsCurrent = (item + 1) == Model.CurrentPage,
                                   URL = Model.UrlTemplate.Replace("{Language}", Model.Language).Replace("{Section}", Model.Section).Replace("{ID}", item.ToString())
                               });
            }

            return result;
        }

        #endregion
    }
}
